/**
 * MongoGenericDAO.java 
 * Copyright © 2014-2016, 杭州泊享网络科技有限公司
 * 
 * @author Liu Tao
 * @create 2015年5月1日
 */
package com.pshare.framework.dao.mongo;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import com.pshare.framework.page.PageInfo;

/**
 * MongoDB持久层
 */
@Service
public abstract class MongoGenericDAO<T> {

	private static final Logger logger = Logger.getLogger(MongoGenericDAO.class);

	@Autowired
	protected MongoTemplate mongoTemplate;

	protected abstract Class<T> getEntityClass();

	/**
	 * 为属性自动注入bean服务
	 * 
	 * @param mongoTemplate
	 */
//	public void setMongoTemplate(MongoTemplate mongoTemplate) {
//		this.mongoTemplate = mongoTemplate;
//	}

	/**
	 * 保存一个对象
	 * 
	 * @param t
	 * @return
	 */
	public void save(T t) {
		mongoTemplate.save(t);
	}

	/**
	 * 根据ID查询对象
	 * 
	 * @param id
	 * @return T
	 */
	public T queryById(String id) {
		if (StringUtils.isBlank(id)) {
			logger.warn("id is blank");
			return null;
		}
		Query query = new Query();
		Criteria criteria = Criteria.where("_id").is(id);
		query.addCriteria(criteria);
		logger.info("[MongoGenericDAO] queryById:" + query);
		return mongoTemplate.findOne(query, getEntityClass());
	}

	/**
	 * 根据条件查询集合
	 * 
	 * @param query 查询条件
	 * @return 满足条件的集合
	 */
	public List<T> queryList(Query query) {
		logger.info("[MongoGenericDAO] queryList:" + query);
		return mongoTemplate.find(query, getEntityClass());
	}

	/**
	 * 通过条件查询单个实体
	 * 
	 * @param query 查询条件
	 * @return T 满足条件的单个实体
	 */
	public T queryOne(Query query) {
		logger.debug("[MongoGenericDAO] queryOne:" + query);
		return mongoTemplate.findOne(query, getEntityClass());
	}

	/**
	 * 分页查询
	 * 
	 * @param query 查询条件
	 * @param start 查询起始值
	 * @param size 一次查询数据的数量
	 * @return List<T> 满足条件的集合
	 */
	public List<T> queryList(Query query, int start, int size) {
		query.skip(start);
		query.limit(size);
		logger.info("[MongoGenericDAO] queryPage:" + query + "(" + start + "," + size + ")");
		List<T> lists = mongoTemplate.find(query, getEntityClass());
		return lists;
	}
	
	public <T> List<T> queryVOList(Query query, int start, int size, Class<T> c) {
		query.skip(start);
		query.limit(size);
		logger.info("[MongoGenericDAO] queryPage:" + query + "(" + start + "," + size + ")");
		List<T> lists = mongoTemplate.find(query, c);
		return lists;
	}

	/**
	 * 根据条件查询库中符合记录的总数,为分页查询服务
	 * 
	 * @param query 查询条件
	 * @return 满足条件的记录总数
	 */
	public Long queryCount(Query query) {
		logger.info("[MongoGenericDAO] queryCount:" + query);
		logger.info("[MongoGenericDAO] queryCount class:" + getEntityClass());
		return mongoTemplate.count(query, getEntityClass());
	}
	
	/**
	 * 分页搜索
	 * @param query
	 * @param pageNo
	 * @param pageSize
	 * @return
	 */
	public PageInfo<T> queryPage(Query query, int pageNo, int pageSize) {
		PageInfo<T> page = new PageInfo<T>(pageNo, pageSize);
		long count = queryCount(query);
		if (count == 0) {
			return page;
		}
		
		List<T> list = queryList(query, page.readOffset(), page.readLimit());
		page.setList(list);
		page.setTotalCount(count);
		return page;
	}
	
	public <T> PageInfo<T> queryVOPage(Query query, int pageNo, int pageSize, Class<T> c) {
		PageInfo<T> page = new PageInfo<T>(pageNo, pageSize);
		long count = queryCount(query);
		if (count == 0) {
			return page;
		}
		
		List<T> list = queryVOList(query, page.readOffset(), page.readLimit(), c);
		page.setList(list);
		page.setTotalCount(count);
		return page;
	}

	/**
	 * 更新满足条件的第一个记录
	 * 
	 * @param query
	 * @param update
	 */
	public void updateFirst(Query query, Update update) {
		logger.info("[MongoGenericDAO] updateFirst:query(" + query + "),update(" + update + ")");
		mongoTemplate.updateFirst(query, update, getEntityClass());
	}

	/**
	 * 更新满足条件的所有记录
	 * 
	 * @param query
	 * @param update
	 */
	public void updateMulti(Query query, Update update) {
		logger.info("[MongoGenericDAO] updateMulti:query(" + query + "),update(" + update + ")");
		mongoTemplate.updateMulti(query, update, getEntityClass());
	}

	/**
	 * 查找更新,如果没有找到符合的记录,则将更新的记录插入库中
	 * 
	 * @param query
	 * @param update
	 */
	public void updateInser(Query query, Update update) {
		logger.info("[MongoGenericDAO] updateInser:query(" + query + "),update(" + update + ")");
		mongoTemplate.upsert(query, update, getEntityClass());
	}

	/**
	 * 根据Id删除对象
	 * 
	 * @param id
	 */
	public void deleteById(String id) {
		if (StringUtils.isBlank(id)) {
			logger.error("id is blank");
			return;
		}
		Criteria criteria = Criteria.where("_id").in(id);
		if (null != criteria) {
			Query query = new Query(criteria);
			logger.info("[MongoGenericDAO] deleteById:" + query);
			if (null != query && queryOne(query) != null) {
				mongoTemplate.remove(query, getEntityClass());
			}
		}
	}

	/**
	 * 删除对象
	 * 
	 * @param t
	 */
	public void delete(T t) {
		logger.info("[MongoGenericDAO] delete:" + t);
		mongoTemplate.remove(t);
	}

}
